package cn.weakup.thread.cyclicbarrier;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author Dawn
 * @version 1.0.0
 * @desc CyclicBarrier是一个同步辅助类，允许一组线程相互等待，直到到达某个公共的屏障点，
 *       通过它可以完成多个线程之间相互等待，只有当每个线程都准备就绪后，才能各自继续往下执行后面的操作
 * @date 2022/5/8
 */
public class CyclicBarrierExample {

    private static AtomicBoolean canReset = new AtomicBoolean(true);

    private static CyclicBarrier cyclicBarrier = new CyclicBarrier(5);

    private static CyclicBarrier cyclicBarrier2 = new CyclicBarrier(5,()->{
        System.out.println(Thread.currentThread().getName() + "最后一个到达临界点");
        System.out.println("已达到临界点，优先执行CyclicBarrier中定义的Runnable任务");

        if(!canReset.get()) {
            canReset.set(true);
        }else {
            canReset.set(false);
        }
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("CyclicBarrier中定义的Runnable任务执行完毕");
    });

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executor = new ThreadPoolExecutor(8, 16, 10,
                TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1000), new ThreadPoolExecutor.AbortPolicy());

        for (int i = 0; i < 10; i++) {
            int finalI = i;

            executor.execute(()-> {
                try {
                    race2(finalI);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }

        /*while (canReset.get()){
            System.out.println("等待临界点的线程数" + cyclicBarrier2.getNumberWaiting());
            cyclicBarrier2.reset();
            System.out.println("重置循环屏障");
            System.out.println("等待临界点的线程数" + cyclicBarrier2.getNumberWaiting());
            TimeUnit.MICROSECONDS.sleep(500);
        }*/
    }

    private static void race2(int threadNum) throws Exception{

        TimeUnit.SECONDS.sleep(1);
        System.out.println(threadNum + " is ready ==> " + Thread.currentThread().getName());
        cyclicBarrier2.await();
        System.out.println(threadNum + " continue ==> " + Thread.currentThread().getName());
    }

    private static void race(int threadNum) throws Exception{

        TimeUnit.SECONDS.sleep(1);
        System.out.println(threadNum + " is ready");

        cyclicBarrier.await();
        System.out.println(threadNum + " continue");
    }
}
